home *** CD-ROM | disk | FTP | other *** search
- //////////////////////////////////////////////////////////////////
- //
- // Balanced.c
- // ----------
- // Balanced tree search and insertion
- //
- //////////////////////////////////////////////////////////////////
-
- #pragma load "managers"
-
- //////////////////////////////////////////////////////////////////
- //
- // Constants and Macros
- //
- //////////////////////////////////////////////////////////////////
-
- #define nil 0
-
- //////////////////////////////////////////////////////////////////
- //
- // Types
- //
- //////////////////////////////////////////////////////////////////
-
- typedef enum {false, true} logical;
-
- typedef struct node
- {
- char *key;
- struct node *left;
- struct node *right;
- int balance;
- char *data;
- } node;
-
- //////////////////////////////////////////////////////////////////
- //
- // Globals
- //
- //////////////////////////////////////////////////////////////////
-
- //////////////////////////////////////////////////////////////////
- //
- // Prototypes
- //
- //////////////////////////////////////////////////////////////////
-
- void initmac();
- node *createnode(char *thekey, char *thedata);
- unsigned int insert(node *parent, char *thekey, char *thedata);
- node *lookup(node *thetable, char *thekey);
- void dump(node *thetable);
- void destroy(node *thetable);
-
- //////////////////////////////////////////////////////////////////
- //
- // main
- // ----
- // Test shell for lookup table package
- //
- //////////////////////////////////////////////////////////////////
-
- main()
- {
-
- node *thetable;
- char thestring[256];
- char command;
- char thekey[256];
- char thedata[256];
- node *thenode;
-
- initmac();
-
- thetable = createnode("", "Data not found - empty key");
- if (thetable == nil)
- {
- printf("\tUnable to create table\n");
- exit(2);
- }
-
- printf("? ");
- while (true)
- {
-
- gets(thestring);
- sscanf(&thestring[2], "%c %s %[^\n]", &command, thekey, thedata);
-
- switch (command)
- {
-
- case 'A':
- case 'a':
- if (insert(thetable, thekey, thedata) == 4)
- printf("\tKey already exists in table\n");
- break;
-
- case 'D':
- case 'd':
- dump(thetable->right);
- break;
-
- case 'F':
- case 'f':
- thenode = lookup(thetable, thekey);
- if (thenode == nil)
- {
- printf("\tKey not found in table\n");
- break;
- }
- printf("\tData is “%s”\n", thenode->data);
- break;
-
- case 'Q':
- case 'q':
- destroy(thetable);
- exit(0);
-
- }
-
- printf("? ");
-
- }
-
- }
-
- //////////////////////////////////////////////////////////////////
- //
- // initmac
- // -------
- // initialize any necessary managers and whatnot.
- //
- //////////////////////////////////////////////////////////////////
-
- void initmac()
- {
-
- InitGraf((Ptr)&qd.thePort);
- SetFScaleDisable(true);
-
- InitCursorCtl(nil);
-
- }
-
- //////////////////////////////////////////////////////////////////
- //
- // createnode
- // ----------
- // create and initialize a new node
- //
- //////////////////////////////////////////////////////////////////
-
- node *createnode(char *thekey, char *thedata)
- {
-
- node *thenode;
- int thelength;
-
- thenode = (node *)NewPtr(sizeof(node));
- if (thenode == nil)
- return(nil);
-
- thelength = 1 + strlen(thekey);
- thenode->key = (char *)NewPtr(thelength);
- if (thenode->key == nil)
- {
- DisposPtr((Ptr)thenode);
- return(nil);
- }
- BlockMove((Ptr)thekey, (Ptr)thenode->key, thelength);
-
- thenode->balance = 0;
- thenode->left = nil;
- thenode->right = nil;
-
- thelength = 1 + strlen(thedata);
- thenode->data = (char *)NewPtr(thelength);
- if (thenode->data == nil)
- {
- DisposPtr((Ptr)thenode->key);
- DisposPtr((Ptr)thenode);
- return(nil);
- }
- BlockMove((Ptr)thedata, (Ptr)thenode->data, thelength);
-
- return(thenode);
-
- }
-
- //////////////////////////////////////////////////////////////////
- //
- // insert
- // ------
- // Insert a new key into the table and correct balance
- // factors recursively. The routine returns a queue of
- // path directions.
- //
- //////////////////////////////////////////////////////////////////
-
- unsigned int insert(node *parent, char *thekey, char *thedata)
- {
-
- int compare;
- node *high;
- unsigned int result;
- node *low;
- node *child;
-
- // if thekey matches this node, then return an error
- // (duplicate keys)
-
- compare = strcmp(thekey, parent->key);
- if (compare == 0)
- return(4);
-
- // if there's a slot for the new node, then create it and return
- // 1 if it is to the left of parent and 2 if to the right
- // else determine high, the next step in the search path
-
- if (compare < 0)
- {
- high = parent->left;
- if (high == nil)
- {
- parent->left = createnode(thekey, thedata);
- return(1);
- }
- }
- else
- {
- high = parent->right;
- if (high == nil)
- {
- parent->right = createnode(thekey, thedata);
- return(2);
- }
- }
-
- // now continue the search by calling “insert” recursively
- // if the result is 0 (no balancing needed at this level) or
- // the result is 4 (duplicate key), return
-
- result = insert(high, thekey, thedata);
- if ((result == 0) || (result == 4))
- return(result);
-
- // the low 4 bits of “result” indicate the direction of the
- // search path leaving “high”; increment high's balance
- // if the path goes left, and decrement it if the path
- // goes right
-
- if (result % 16 == 1)
- high->balance++;
- else
- high->balance--;
-
- // if the balance is now zero, no further correction of balances
- // is needed, so return
- // if it's ±1, push the direction away from “parent” onto the
- // “result” stack and return it
- // if it's ±2, continue to balancing transformation
-
- switch (high->balance)
- {
- case 0:
- return(0);
- case 1:
- case -1:
- return((result << 4) + ((compare < 0) ? 1 : 2));
- case 2:
- case -2:
- break;
- }
-
- // use the direction away from “high” to find “low”, then
- // switch on that direction and the next one
- // the easiest way to follow these transformations is to
- // refer to the pictures
-
- low = (result % 16 == 1) ? high->left : high->right;
- switch (result % 256)
- {
-
- case 0x11: // left-left case
-
- high->left = low->right;
- low->right = high;
- if (compare < 0)
- parent->left = low;
- else
- parent->right = low;
- high->balance = 0;
- low->balance = 0;
- return(0);
-
- case 0x12: // right-left case
-
- child = low->left;
- high->right = child->left;
- low->left = child->right;
- if (compare < 0)
- parent->left = child;
- else
- parent->right = child;
- child->left = high;
- child->right = low;
- child->balance = 0;
- low->balance = 0;
- high->balance = 0;
- result &= 0xF00;
- if (result == 0x100)
- low->balance = -1;
- else if (result == 0x200)
- high->balance = 1;
- return(0);
-
- case 0x21: // left-right case
-
- child = low->right;
- low->right = child->left;
- high->left = child->right;
- if (compare < 0)
- parent->left = child;
- else
- parent->right = child;
- child->left = low;
- child->right = high;
- child->balance = 0;
- low->balance = 0;
- high->balance = 0;
- result &= 0xF00;
- if (result == 0x100)
- high->balance = -1;
- else if (result == 0x200)
- low->balance = 1;
- return(0);
-
- case 0x22: // right-right case
-
- high->right = low->left;
- low->left = high;
- if (compare < 0)
- parent->left = low;
- else
- parent->right = low;
- high->balance = 0;
- low->balance = 0;
- return(0);
-
- }
-
- }
-
- //////////////////////////////////////////////////////////////////
- //
- // lookup
- // ------
- // Find a key in the table
- //
- //////////////////////////////////////////////////////////////////
-
- node *lookup(node *thetable, char *thekey)
- {
-
- node *thenode;
- int compare;
-
- thenode = thetable;
-
- while (compare = strcmp(thekey, thenode->key))
- {
- if (compare < 0)
- thenode = thenode->left;
- else
- thenode = thenode->right;
- if (thenode == nil)
- return(nil);
- }
-
- return(thenode);
-
- }
-
- //////////////////////////////////////////////////////////////////
- //
- // dump
- // ----
- // Display the table, node by node
- //
- //////////////////////////////////////////////////////////////////
-
- void dump(node *thetable)
- {
-
- if (thetable == nil)
- return;
-
- dump(thetable->left);
-
- printf("%10s - %2d - %10s - %10s\n",
- thetable->key, thetable->balance,
- thetable->left ? thetable->left->key : "nil",
- thetable->right ? thetable->right->key : "nil");
-
- dump(thetable->right);
-
- }
-
- //////////////////////////////////////////////////////////////////
- //
- // destroy
- // -------
- // Dispose of the table
- //
- //////////////////////////////////////////////////////////////////
-
- void destroy(node *thetable)
- {
-
- if (thetable == nil)
- return;
-
- destroy(thetable->left);
- destroy(thetable->right);
-
- DisposPtr((Ptr)thetable->key);
- DisposPtr((Ptr)thetable->data);
- DisposPtr((Ptr)thetable);
-
- }
-
- //////////////////////////////////////////////////////////////////
-